package com.yunchao.feature.business.presentation.screen.details

import androidx.lifecycle.viewModelScope
import com.yunchao.feature.base.data.CustomAudioManager
import com.yunchao.feature.base.domain.result.errorMsg
import com.yunchao.feature.base.presentation.viewmodel.BaseAction
import com.yunchao.feature.base.presentation.viewmodel.BaseEffect
import com.yunchao.feature.base.presentation.viewmodel.BaseState
import com.yunchao.feature.base.presentation.viewmodel.BaseViewModel
import com.yunchao.feature.business.domain.model.BusinessInfoModel
import com.yunchao.feature.business.domain.model.BusinessPackModel
import com.yunchao.feature.business.domain.repository.BusinessRepository
import com.yunchao.feature.business.presentation.screen.details.BusinessDetailsViewModel.Action
import com.yunchao.feature.business.presentation.screen.details.BusinessDetailsViewModel.UiEffect
import com.yunchao.feature.business.presentation.screen.details.BusinessDetailsViewModel.UiState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch

internal class BusinessDetailsViewModel(
    private val businessRepository: BusinessRepository,
    private val customAudioManager: CustomAudioManager
) :
    BaseViewModel<UiState, Action, UiEffect>(UiState.Idle) {
    private var loopJob: Job? = null

    fun loadBusinessInfo(args: BusinessDetailsFragmentArgs) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        businessRepository.getBusinessInfo(
            tranTypeID = args.tranTypeId,
            tranID = args.tranId
        ).onSuccess {
            sendAction(Action.LoadBusinessSuccess(it)).apply {
                postSideEffect(UiEffect.HideLoading)
            }
        }.onFailure {
            postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                postSideEffect(UiEffect.HideLoading)
            }
        }
    }

    fun setupPower(isLoop: Boolean) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        businessRepository.setupPower(isLoop)
            .onSuccess {
                postSideEffect(UiEffect.ShowToast("功率设置成功")).apply {
                    customAudioManager.playSound(1)
                }.apply {
                    postSideEffect(UiEffect.HideLoading)
                }
            }.onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(2)
                }.apply {
                    postSideEffect(UiEffect.HideLoading)
                }
            }
    }

    fun submitBusiness(model: BusinessInfoModel, models: List<BusinessPackModel>) =
        viewModelScope.launch {
            postSideEffect(UiEffect.ShowLoading)
            businessRepository.submitBusiness(model, models)
                .onSuccess {
                    postSideEffect(UiEffect.SubmitSuccess(it)).apply {
                        postSideEffect(UiEffect.HideLoading)
                    }
                }.onFailure {
                    postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                        postSideEffect(UiEffect.HideLoading)
                    }
                }
        }

    fun updateBusiness(model: BusinessInfoModel, items: List<BusinessPackModel>, isLoop: Boolean) =
        viewModelScope.launch {
            loopJob?.cancel(); loopJob = null
            businessRepository.inventoryStop(model, items, isLoop)
        }

    fun openLock(packInfoMap: Map<String, BusinessPackModel>, business: BusinessInfoModel) =
        viewModelScope.launch {
            postSideEffect(UiEffect.ShowLoading)
            businessRepository.openLockWriteLogistics(packInfoMap, business)
                .onSuccess {
                    sendAction(Action.GetPackInfoSuccess(packInfo = it)).apply {
                        customAudioManager.playSound(1)
                    }.apply { postSideEffect(UiEffect.HideLoading) }
                }.onFailure {
                    postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                        customAudioManager.playSound(2)
                    }.apply {
                        postSideEffect(UiEffect.HideLoading)
                    }
                }
        }

    fun closeLock(
        packInfo: BusinessPackModel,
        business: BusinessInfoModel,
        busiInfo: BusinessPackModel,
        pageNumber: Int
    ) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        businessRepository.closeLockWriteLogistics(
            taskInfo = business, packInfo = packInfo, busiInfo = busiInfo, pageNumber = pageNumber
        ).onSuccess {
            sendAction(Action.GetPackInfoSuccess(packInfo = it)).apply {
                customAudioManager.playSound(1)
            }.apply { postSideEffect(UiEffect.HideLoading) }
        }.onFailure {
            postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                customAudioManager.playSound(2)
            }.apply {
                postSideEffect(UiEffect.HideLoading)
            }
        }
    }

    fun inventoryLoop(model: BusinessInfoModel, packInfoMap: Map<String, BusinessPackModel>) {
        loopJob = viewModelScope.launch {
            businessRepository.inventoryLoop(model, packInfoMap)
                .flowOn(Dispatchers.Default)
                .collect {
                    sendAction(Action.GetPackInfoSuccess(packInfoList = it)).apply {
                        customAudioManager.playSound(1)
                    }.apply { postSideEffect(UiEffect.HideLoading) }
                }
        }
    }

    fun inventoryOnce(model: BusinessInfoModel, packInfoMap: Map<String, BusinessPackModel>) =
        viewModelScope.launch {
            postSideEffect(UiEffect.ShowLoading)
            businessRepository.inventoryOnce(model, packInfoMap)
                .onSuccess {
                    sendAction(Action.GetPackInfoSuccess(packInfo = it)).apply {
                        customAudioManager.playSound(1)
                    }.apply { postSideEffect(UiEffect.HideLoading) }
                }
                .onFailure {
                    postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                        customAudioManager.playSound(2)
                    }.apply { postSideEffect(UiEffect.HideLoading) }
                }

        }


    internal sealed interface Action : BaseAction<UiState> {
        data class LoadBusinessSuccess(val businessInfoModel: BusinessInfoModel) : Action {
            override fun reduce(state: UiState): UiState = UiState.Success(businessInfoModel)
        }

        data class GetPackInfoSuccess(
            val packInfo: BusinessPackModel? = null,
            val packInfoList: List<BusinessPackModel> = emptyList()
        ) : Action {
            override fun reduce(state: UiState): UiState =
                UiState.GetPackInfo(packInfo, packInfoList)
        }
    }

    internal sealed interface UiState : BaseState {
        data class Success(val businessInfoModel: BusinessInfoModel) : UiState
        data class GetPackInfo(
            val packInfo: BusinessPackModel? = null,
            val packInfoList: List<BusinessPackModel> = emptyList()
        ) : UiState

        data object Idle : UiState
    }

    internal sealed interface UiEffect : BaseEffect {
        data object ShowLoading : UiEffect
        data object HideLoading : UiEffect
        data class ShowToast(val msg: String) : UiEffect
        data class SubmitSuccess(val msg: String) : UiEffect

    }
}